package net.oschina.j2cache.redis;

import java.io.InputStream;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.sf.ehcache.CacheException;
import redis.clients.jedis.BinaryJedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis 连接池
 * @author Winter Lau
 */
public class RedisPool extends JedisPool {
	private final static Log log = LogFactory.getLog(RedisPool.class);
	private final static String CONFIG_FILE = "/redis.properties";
	private static JedisPoolConfig config = new JedisPoolConfig();
	private static JedisPool pool;
	private static Properties properties;

	private final static String host;
	private final static int port;
	private final static int timeout;
	private final static String password;
	private final static int database;
	
	static {
		properties = new Properties();
		try {
			InputStream in= RedisPool.class.getResourceAsStream(CONFIG_FILE);
			if(in == null)
				in = RedisPool.class.getClassLoader().getParent().getResourceAsStream(CONFIG_FILE);
			properties.load(in);
			
			host = getProperty("host","127.0.0.1");
			password = properties.getProperty("password", null);
			
			port = getProperty("port", 6379);
			timeout = getProperty("timeout", 2000);
			database = getProperty("database", 0);
			
			config.setWhenExhaustedAction((byte)getProperty("whenExhaustedAction",1));
			config.setMaxIdle(getProperty("maxIdle", 10));
			config.setMinIdle(getProperty("minIdle", 5));
			config.setMaxActive(getProperty("maxActive", 50));
			config.setMaxWait(getProperty("maxWait", 100));
			config.setTestWhileIdle(getProperty("testWhileIdle", false));
			config.setTestOnBorrow(getProperty("testOnBorrow", true));
			config.setTestOnReturn(getProperty("testOnReturn", false));
			config.setNumTestsPerEvictionRun(getProperty("numTestsPerEvictionRun", 10));
			config.setMinEvictableIdleTimeMillis(getProperty("minEvictableIdleTimeMillis", 1000));
			config.setSoftMinEvictableIdleTimeMillis(getProperty("softMinEvictableIdleTimeMillis", 10));
			config.setTimeBetweenEvictionRunsMillis(getProperty("timeBetweenEvictionRunsMillis", 10));
			config.lifo = getProperty("lifo", false);
			
			if(null != in)
				in.close();
			log.info("----------------------------------------------------------------------");
			log.info("--Using JedisPool config:"+properties.toString()+"--");
			log.info("----------------------------------------------------------------------");
		} catch (Exception e) {
			throw new CacheException(
					"CacheException:RedisConfig init failed cause by:", e);
		}
	}

	private RedisPool(JedisPoolConfig config) {
		super(config, host, port, timeout, password, database);
	}

	public static JedisPool me() {
		if (null == pool) {
			synchronized (RedisPool.class) {
				if (null == pool) {
					pool = new RedisPool(config);
				}
			}
		}
		return pool;
	}

    public static void returnResource(BinaryJedis jedis,boolean isBrokenResource) {
    	if(null == jedis)
    		return;
        if(isBrokenResource){     
                RedisPool.me().returnBrokenResource(jedis);
                jedis = null;
        }
        else
            RedisPool.me().returnResource(jedis);
    }

	private static String getProperty(String key, String defaultValue) {
		return properties.getProperty(key, defaultValue).trim();
	}

	private static int getProperty(String key, int defaultValue) {
		try{
			return Integer.parseInt(properties.getProperty(key, String.valueOf(defaultValue)).trim());
		}catch(Exception e){
			return defaultValue;
		}
	}

	private static boolean getProperty(String key, boolean defaultValue) {
		return "true".equalsIgnoreCase(properties.getProperty(key, String.valueOf(defaultValue)).trim());
	}
}
